<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/', 'HomeController@index');

Route::get('/posts', 'HomeController@index');

Route::get('/posts/{id}', 'HomeController@show');

Route::controllers([
    'search' => 'SearchController',
//    'auth' => 'Auth\AuthController'
]);

Route::group(['prefix' => 'backend', 'namespace' => 'Backend'], function() {
    // 对整个路由组使用 middleware, 但排除指定的个别路由, 使用此种方法实现
    // 因为在路由组中使用了 namespace, 所以此处使用绝对命名空间指定控制器
    Route::controllers([
        'auth' => '\App\Http\Controllers\Auth\AuthController',
        'password' => '\App\Http\Controllers\Auth\PasswordController',
        'user' => 'UserController',
    ]);
//    Route::get('auth/login', '\App\Http\Controllers\Auth\AuthController@getLogin');
//    Route::post('auth/login', '\App\Http\Controllers\Auth\AuthController@postLogin');
//    Route::get('auth/logout', '\App\Http\Controllers\Auth\AuthController@getLogout');

    Route::group(['middleware' => 'auth'], function() {
        Route::resource('posts', 'PostController');
    });
});

// 测试路由组 中中间件的使用方法, Laravel群友提问
// 该方法是可行的, 组与普通的请求不同, 如 Route::get('group/middleware', ['middleware' => 'auth', function () {  }])
Route::group(['namespace' => 'Admin', 'middleware' => 'auth'], function() {
   Route::get('group/middleware', function() {
       return 'test';
   });
});

Route::group(['prefix' => 'wechat', 'namespace' => 'Wechat'], function() {
    Route::controllers([
        'valid' => 'ValidController',
    ]);
});

Route::get('markdown', function() {
    $markdown = <<<EOF
# H1
## H2
### H3
#### H4
##### H5
###### H6
Header 1
========
Header 2
--------


*italic*

**bold**

_italic_

__bold__


*   A list item.

    With multiple paragraphs.

*   Bar


+   Red
+   Green
+   Blue


-   Red
-   Green
-   Blue


1.  Foo
2.  Bar


*   Abacus
    *   answer
*   Bubbles
    1.  bunk
    2.  bupkis
        *   BELITTLER
    3.  burper
*   Cunning

1986\. What a great season.

1986. What a great season.

\*this text is surrounded by literal asterisks\*


> Email-style angle brackets
> are used for blockquotes.

> > And, they can be nested.

> #### Headers in blockquotes
>
> * You can quote a list.
> * Etc.

`<code>`

This is a normal paragraph.

    This is a preformatted
    code block.


---

* * *

- - - -

Manual Line Breaks

End a line with two or more spaces:
Roses are red,
Violets are blue.

[Link example](http://google.com/ "Title")

![alt text](/assets/demoyy/img/title.jpg "Title")
EOF;

    return Markdown::string($markdown);
});

Route::get('post/1', function() {
    $article = App\Post::find(1);
    $random = App\Post::random(6)->isApproved()->get();
    $comments = App\Comment::recent(6)->get();
    $markdown = file_get_contents(storage_path('markdown/learn-composer.md'));
    $markdown = Markdown::string($markdown);
    return view('markdown', compact('markdown', 'article', 'random', 'comments'));
});

Route::get('md5/{string}', function($string) {
    return md5($string);
});

Route::get('getIPLoc', function() {
    function realIP() {
        static $realIP = NULL;

        if ($realIP !== NULL) {
            return $realIP;
        }

        if (isset($_SERVER)) {
            dump('$_SERVER isset');
            if (isset($_SERVER['HTTP_TRUECLIENTIP']) && trim($_SERVER['HTTP_TRUECLIENTIP']) != 'unknown') {
                dump('$_SERVER["HTTP_TRUECLIENTIP"] isset');
                $realIP = $_SERVER['HTTP_TRUECLIENTIP'];
            } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                dump('$_SERVER["HTTP_X_FORWARDED_FOR"] isset');
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                /* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
                foreach ($arr AS $ip) {
                    $ip = trim($ip);
                    if ($ip != 'unknown') {
                        $realIP = $ip;
                        break;
                    }
                }
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                dump('$_SERVER["HTTP_CLIENT_IP"] isset');
                $realIP = $_SERVER['HTTP_CLIENT_IP'];
            } else {
                if (isset($_SERVER['REMOTE_ADDR'])) {
                    dump('$_SERVER["REMOTE_ADDR"] isset');
                    $realIP = $_SERVER['REMOTE_ADDR'];
                } else {
                    dump('ip unknown');
                    $realIP = 'unknown';
                }
            }
        } else {
            dump('$_SERVER is not set');
            if (getenv('HTTP_X_FORWARDED_FOR')) {
                dump('getenv("HTTP_X_FORWARDED_FOR")');
                $realIP = getenv('HTTP_X_FORWARDED_FOR');
            } elseif (getenv('HTTP_CLIENT_IP')) {
                dump('getenv("HTTP_CLIENT_IP")');
                $realIP = getenv('HTTP_CLIENT_IP');
            } else {
                dump('getenv("REMOTE_ADDR")');
                $realIP = getenv('REMOTE_ADDR');
            }
        }

        preg_match("/[\d\.]{7,15}/", $realIP, $onlineIP);
        $realIP = !empty($onlineIP[0]) ? $onlineIP[0] : 'unknown';

        return $realIP;
    }
    $ip = realIP();
    dump($ip);
    $url = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip='.$ip;
    $ch = curl_init($url);
    //curl_setopt($ch,CURLOPT_ENCODING ,'utf8');
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; // 获取数据返回
    $location = curl_exec($ch);
    dump($location);
    $location = json_decode($location);
    curl_close($ch);
    dump($location);
    if ($location === FALSE) return "";
    if (empty($location->desc)) {
        $loc = $location->country;
    } else {
        $loc = $location->desc;
    }
    if (mb_substr($loc,0,2) == '中国') {
        return 1;
    } else {
        return 0;
    }
});

Route::get('faker', function() {
    $faker = Faker\Factory::create($locale = 'zh_CN');
//    $data['name'] = $faker->name;
//    $data['address'] = $faker->address;
//    $data['text'] = $faker->text;
//    $data['email'] = $faker->email;

    $data['base'][] = $faker->randomDigit;              // 7
    $data['base'][] = $faker->randomDigitNotNull;       // 5
    $data['base'][] = $faker->randomNumber($nbDigits = NULL);   // 79907610
    $data['base'][] = $faker->randomFloat($nbMaxDecimals = NULL, $min = 0, $max = NULL);    // 48.8932
    $data['base'][] = $faker->numberBetween($min = 1000, $max = 9000);      // 8567
    $data['base'][] = $faker->randomLetter;             // 'b'
    $data['base'][] = $faker->randomElements($array = array ('a','b','c'), $count = 1);     // array('c')
    $data['base'][] = $faker->randomElement($array = array ('a','b','c'));  // 'b'
    $data['base'][] = $faker->shuffle('hello, world');  // 'rlo,h eoldlw'
    $data['base'][] = $faker->shuffle(array(1, 2, 3));  // array(2, 1, 3)
    $data['base'][] = $faker->numerify('Hello ###');    // 'Hello 609'
    $data['base'][] = $faker->lexify('Hello ???');      // 'Hello wgt'
    $data['base'][] = $faker->bothify('Hello ##??');    // 'Hello 42jz'
    $data['base'][] = $faker->asciify('Hello ***');     // 'Hello R6+'
    $data['base'][] = $faker->regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}');   // sm0@y8k96a.ej

    $data['lorem'][] = $faker->word;                    // 'aut'
    $data['lorem'][] = $faker->words($nb = 3);          // array('porro', 'sed', 'magni')
    $data['lorem'][] = $faker->sentence($nbWords = 6);  // 'Sit vitae voluptas sint non voluptates.'
    $data['lorem'][] = $faker->sentences($nb = 3);      // array('Optio quos qui illo error.', 'Laborum vero a officia id corporis.', 'Saepe provident esse hic eligendi.')
    $data['lorem'][] = $faker->paragraph($nbSentences = 3); // 'Ut ab voluptas sed a nam. Sint autem inventore aut officia aut aut blanditiis. Ducimus eos odit amet et est ut eum.'
    $data['lorem'][] = $faker->paragraphs($nb = 3);     // array('Quidem ut sunt et quidem est accusamus aut. Fuga est placeat rerum ut. Enim ex eveniet facere sunt.', 'Aut nam et eum architecto fugit repellendus illo. Qui ex esse veritatis.', 'Possimus omnis aut incidunt sunt. Asperiores incidunt iure sequi cum culpa rem. Rerum exercitationem est rem.')
    $data['lorem'][] = $faker->text($maxNbChars = 200); // 'Fuga totam reiciendis qui architecto fugiat nemo. Consequatur recusandae qui cupiditate eos quod.'

    $data['person'][] = $faker->title($gender = null|'male'|'female');     // 'Ms.'
    $data['person'][] = $faker->titleMale;                                 // 'Mr.'
    $data['person'][] = $faker->titleFemale;                               // 'Ms.'
//    $data['person'][] = $faker->suffix;                                    // 'Jr.'       zh_CN不支持
    $data['person'][] = $faker->name($gender = null|'male'|'female');      // 'Dr. Zane Stroman'
    $data['person'][] = $faker->firstName($gender = null|'male'|'female'); // 'Maynard'
    $data['person'][] = $faker->firstNameMale;                             // 'Maynard'
    $data['person'][] = $faker->firstNameFemale;                           // 'Rachel'
    $data['person'][] = $faker->lastName;                                  // 'Zulauf'

//    $data['address'][] = $faker->cityPrefix;              // 'Lake'       zh_CN不支持
//    $data['address'][] = $faker->secondaryAddress;        // 'Suite 961'  zh_CN不支持
//    $data['address'][] = $faker->state;                   // 'NewMexico'  zh_CN不支持
//    $data['address'][] = $faker->stateAbbr;               // 'OH'         zh_CN不支持
    $data['address'][] = $faker->citySuffix;              // 'borough'
    $data['address'][] = $faker->streetSuffix;            // 'Keys'
    $data['address'][] = $faker->buildingNumber;          // '484'
    $data['address'][] = $faker->city;                    // 'West Judge'
    $data['address'][] = $faker->streetName;              // 'Keegan Trail'
    $data['address'][] = $faker->streetAddress;           // '439 Karley Loaf Suite 897'
    $data['address'][] = $faker->postcode;                // '17916'
    $data['address'][] = $faker->address;                 // '8888 Cummings Vista Apt. 101, Susanbury, NY 95473'
    $data['address'][] = $faker->country;                 // 'Falkland Islands (Malvinas)'
    $data['address'][] = $faker->latitude;                // 77.147489
    $data['address'][] = $faker->longitude;               // 86.211205

    $data['phoneNumber'][] = $faker->phoneNumber;             // '201-886-0269 x3767'
//已弃用    $data['address'][] = $faker->tollFreePhoneNumber;     // '(888) 937-7238'

//    $data['company'][] = $faker->catchPhrase;             // 'Monitored regional contingency'     zh_CN不支持
//    $data['company'][] = $faker->bs;                      // 'e-enable robust architectures'      zh_CN不支持
    $data['company'][] = $faker->company;                 // 'Bogan-Treutel'
    $data['company'][] = $faker->companySuffix;           // 'and Sons'

    $data['text'][] = $faker->realText($maxNbChars = 200, $indexSize = 2); // "And yet I wish you could manage it?) 'And what are they made of?' Alice asked in a shrill, passionate voice. 'Would YOU like cats if you were never even spoke to Time!' 'Perhaps not,' Alice replied."

    $data['datetime'][] = $faker->unixTime($max = 'now');                // 58781813
    $data['datetime'][] = $faker->dateTime($max = 'now');                // DateTime('2008-04-25 08:37:17')
    $data['datetime'][] = $faker->dateTimeAD($max = 'now');              // DateTime('1800-04-29 20:38:49')
    $data['datetime'][] = $faker->iso8601($max = 'now');                 // '1978-12-09T10:10:29+0000'
    $data['datetime'][] = $faker->date($format = 'Y-m-d', $max = 'now'); // '1979-06-09'
    $data['datetime'][] = $faker->time($format = 'H:i:s', $max = 'now'); // '20:49:42'
    $data['datetime'][] = $faker->dateTimeBetween($startDate = '-30 years', $endDate = 'now'); // DateTime('2003-03-15 02:00:49')
//    $data['datetime'][] = $faker->dateTimeInInterval($startDate = '-30 years', $interval = '+ 5 days'); // DateTime('2003-03-15 02:00:49')
    $data['datetime'][] = $faker->dateTimeThisCentury($max = 'now');     // DateTime('1915-05-30 19:28:21')
    $data['datetime'][] = $faker->dateTimeThisDecade($max = 'now');      // DateTime('2007-05-29 22:30:48')
    $data['datetime'][] = $faker->dateTimeThisYear($max = 'now');        // DateTime('2011-02-27 20:52:14')
    $data['datetime'][] = $faker->dateTimeThisMonth($max = 'now');       // DateTime('2011-10-23 13:46:23')
    $data['datetime'][] = $faker->amPm($max = 'now');                    // 'pm'
    $data['datetime'][] = $faker->dayOfMonth($max = 'now');              // '04'
    $data['datetime'][] = $faker->dayOfWeek($max = 'now');               // 'Friday'
    $data['datetime'][] = $faker->month($max = 'now');                   // '06'
    $data['datetime'][] = $faker->monthName($max = 'now');               // 'January'
    $data['datetime'][] = $faker->year($max = 'now');                    // '1993'
    $data['datetime'][] = $faker->century;                               // 'VI'
    $data['datetime'][] = $faker->timezone;                              // 'Europe/Paris'

    $data['internet'][] = $faker->email;                   // 'tkshlerin@collins.com'
    $data['internet'][] = $faker->safeEmail;               // 'king.alford@example.org'
    $data['internet'][] = $faker->freeEmail;               // 'bradley72@gmail.com'
    $data['internet'][] = $faker->companyEmail;            // 'russel.durward@mcdermott.org'
    $data['internet'][] = $faker->freeEmailDomain;         // 'yahoo.com'
    $data['internet'][] = $faker->safeEmailDomain;         // 'example.org'
    $data['internet'][] = $faker->userName;                // 'wade55'
    $data['internet'][] = $faker->password;                // 'k&|X+a45*2['
    $data['internet'][] = $faker->domainName;              // 'wolffdeckow.net'
    $data['internet'][] = $faker->domainWord;              // 'feeney'
    $data['internet'][] = $faker->tld;                     // 'biz'
    $data['internet'][] = $faker->url;                     // 'http://www.skilesdonnelly.biz/aut-accusantium-ut-architecto-sit-et.html'
    $data['internet'][] = $faker->slug;                    // 'aut-repellat-commodi-vel-itaque-nihil-id-saepe-nostrum'
    $data['internet'][] = $faker->ipv4;                    // '109.133.32.252'
    $data['internet'][] = $faker->localIpv4;               // '10.242.58.8'
    $data['internet'][] = $faker->ipv6;                    // '8e65:933d:22ee:a232:f1c1:2741:1f10:117c'
    $data['internet'][] = $faker->macAddress;              // '43:85:B7:08:10:CA'

    $data['useragent'][] = $faker->userAgent;              // 'Mozilla/5.0 (Windows CE) AppleWebKit/5350 (KHTML, like Gecko) Chrome/13.0.888.0 Safari/5350'
    $data['useragent'][] = $faker->chrome;                 // 'Mozilla/5.0 (Macintosh; PPC Mac OS X 10_6_5) AppleWebKit/5312 (KHTML, like Gecko) Chrome/14.0.894.0 Safari/5312'
    $data['useragent'][] = $faker->firefox;                // 'Mozilla/5.0 (X11; Linuxi686; rv:7.0) Gecko/20101231 Firefox/3.6'
    $data['useragent'][] = $faker->safari;                 // 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_7_1 rv:3.0; en-US) AppleWebKit/534.11.3 (KHTML, like Gecko) Version/4.0 Safari/534.11.3'
    $data['useragent'][] = $faker->opera;                  // 'Opera/8.25 (Windows NT 5.1; en-US) Presto/2.9.188 Version/10.00'
    $data['useragent'][] = $faker->internetExplorer;       // 'Mozilla/5.0 (compatible; MSIE 7.0; Windows 98; Win 9x 4.90; Trident/3.0)'

    $data['payment'][] = $faker->creditCardType;                 // 'MasterCard'
    $data['payment'][] = $faker->creditCardNumber;               // '4485480221084675'
    $data['payment'][] = $faker->creditCardExpirationDate;       // 04/13
    $data['payment'][] = $faker->creditCardExpirationDateString; // '04/13'
    $data['payment'][] = $faker->creditCardDetails;              // array('MasterCard', '4485480221084675', 'Aleksander Nowak', '04/13') // Generates a random IBAN. Set $countryCode to null for a random country
//    $data['payment'][] = $faker->iban($countryCode);             // 'IT31A8497112740YZ575DJ28BP4'
    $data['payment'][] = $faker->swiftBicNumber;                 // RZTIAT22263

    $data['color'][] = $faker->hexcolor;               // '#fa3cc2'
    $data['color'][] = $faker->rgbcolor;               // '0,255,122'
    $data['color'][] = $faker->rgbColorAsArray;        // array(0,255,122)
    $data['color'][] = $faker->rgbCssColor;            // 'rgb(0,255,122)'
    $data['color'][] = $faker->safeColorName;          // 'fuchsia'
    $data['color'][] = $faker->colorName;              // 'Gainsbor'

//    $data['file'][] = $faker->fileExtension;          // 'avi'
//    $data['file'][] = $faker->mimeType;               // 'video/x-msvideo'  // Copy a random file from the source to the target directory and returns the fullpath or filename
//    $data['file'][] = $faker->file($sourceDir = '/tmp', $targetDir = '/tmp'); // '/path/to/targetDir/13b73edae8443990be1aa8f1a483bc27.jpg'
//    $data['file'][] = $faker->file($sourceDir, $targetDir, false); // '13b73edae8443990be1aa8f1a483bc27.jpg'

    $data['image'][] = $faker->imageUrl($width = 640, $height = 480); // 'http://lorempixel.com/640/480/'
    $data['image'][] = $faker->imageUrl($width, $height, 'cats');     // 'http://lorempixel.com/800/600/cats/'
    $data['image'][] = $faker->imageUrl($width, $height, 'cats', true, 'Faker'); // 'http://lorempixel.com/800/400/cats/Faker'
    $data['image'][] = $faker->image($dir = '/tmp', $width = 640, $height = 480); // '/tmp/13b73edae8443990be1aa8f1a483bc27.jpg'
    $data['image'][] = $faker->image($dir, $width, $height, 'cats');  // 'tmp/13b73edae8443990be1aa8f1a483bc27.jpg' it's a cat!
    $data['image'][] = $faker->image($dir, $width, $height, 'cats', true, 'Faker'); // 'tmp/13b73edae8443990be1aa8f1a483bc27.jpg' it's a cat with Faker text

    $data['uuid'][] = $faker->uuid;                   // '7e57d004-2b97-0e7a-b45f-5387367791cd'

    $data['barcode'][] = $faker->ean13;          // '4006381333931'
    $data['barcode'][] = $faker->ean8;           // '73513537'
    $data['barcode'][] = $faker->isbn13;         // '9790404436093'
    $data['barcode'][] = $faker->isbn10;         // '4881416324'

    $data['miscellaneous'][] = $faker->boolean($chanceOfGettingTrue = 50); // true
    $data['miscellaneous'][] = $faker->md5;           // 'de99a620c50f2990e87144735cd357e7'
    $data['miscellaneous'][] = $faker->sha1;          // 'f08e7f04ca1a413807ebc47551a40a20a0b4de5c'
    $data['miscellaneous'][] = $faker->sha256;        // '0061e4c60dac5c1d82db0135a42e00c89ae3a333e7c26485321f24348c7e98a5'
    $data['miscellaneous'][] = $faker->locale;        // en_UK
    $data['miscellaneous'][] = $faker->countryCode;   // UK
    $data['miscellaneous'][] = $faker->languageCode;  // en
    $data['miscellaneous'][] = $faker->currencyCode;  // EUR

    $data['biased'][] = $faker->biasedNumberBetween($min = 10, $max = 20, $function = 'sqrt');

    dd($data);

});

Route::get('/closure', function() {

    $test = function($name) {
        echo 'hello, ', $name;
    };
    $test("Demo");die;


    $f = function ($num = null) {
        return $num === null ? 100 : $num;
    };

    function testClosure(Closure $callback)
    {
        return $callback(300);
    }

    $a = testClosure($f);
    var_dump($a);exit;


    class ATest {

        public $base = 100;

    }

    class BTest {

        private $base = 1000;
    }

    $f = function () {
        return $this->base + 3;
    };


    $a = Closure::bind($f, new ATest);
    print_r($a());

    echo PHP_EOL;

    $b = Closure::bind($f, new BTest, 'BTest');
    print_r($b());

    echo PHP_EOL;
    exit;
});

Route::get('foo', function () {
//    $collection = collect(['taylor', 'abigail', null])
//        ->map(function($name) {
//            return strtoupper($name);
//        })
//            ->reject(function($name) {
//                return empty($name);
//            });

//    use Illuminate\Support\Collection;
//    $collection = Collection::make(['first' => 1, 'second' => 2, 'third' => 3]);

    $collection = collect(['first' => 1, 'second' => 2, 'third' => 3]);
    return dd($collection);
});

Route::get('encryption', function () {
    $encrypted = Crypt::encrypt('secret');
    $decrypted = Crypt::decrypt($encrypted);
    $arr[] = $encrypted;
    $arr[] = $decrypted;
    return dd($arr);
});

Route::get('errors', function () {
    Log::info('This is some useful information.');
    Log::warning('Something could be going wrong.');
    abort(404);
    Log::error('Something is really going wrong.');
//    abort(403, 'Unauthorized action.');
});

Route::get('hasing', function () {
    $passwd[] = Hash::make('secret');
    $passwd[] = bcrypt('secret');
    if (Hash::check('secret', $passwd[1])) {
        return dd(true);
    }
    return dd($passwd);
});

Route::get('helpers', function () {
    // 如果给定的键不在数组中，array_add 函数会把给定的键值对加到数组中
//    $array = ['foo' => 'bar'];
//    $array = array_add($array, 'key', 'value');
//    return dd($array);

    // array_divide 函数返回两个数组，一个包含原本数组的键，另一个包含原本数组的值
//    $array = ['foo' => 'bar', 'name' => 'Demo'];
//    $list = array_divide($array);
//    return dd($list);


    // array_dot 函数把多维数组扁平化成一维数组，并用「点」符号表示深度
//    $array = ['foo' => ['bar' => ['baz' => 'dot'], 'baz' => 'dot']];
//    $array = array_dot($array);
//    return dd($array);

    // array_except 函数从数组移除给定的键值对
//    $array = ['foo' => 'fooName', 'bar' => 'barName', 'baz' => 'bazName'];
//    $array = array_except($array, ['foo', 'bar']);
//    return dd($array);

    // array_fetch 函数返回包含被选择的嵌套元素的扁平化数组
//    $array = [
//        ['developer' => ['name' => 'Taylor']],
//        ['developer' => ['name' => 'Dayle']]
//    ];
//    $array = array_fetch($array, 'developer.name');
//    return dd($array);

    // array_first 函数返回数组中第一个通过给定的测试为真的元素, 也可以传递默认值当作第三个参数
//    $array = ['first' => 'firstName', 'second' => 'secondName', 'third' => 'thirdName'];
//    $value = array_first($array, function($key, $value) {
//        return $key == 'second';
//    }, 'default');
//    return dd($value);

    // array_last 函数返回数组中最后一个通过给定的测试为真的元素, 也可以传递默认值当作第三个参数
//    $array = [1, 2, 3, 4, 5];
//    $value = array_last($array, function($key, $value) {
//        return $value > 3;
//    }, 'default');
//    return dd($value);

    // array_flatten 函数将会把多维数组扁平化成一维
//    $array = [
//        'name' => 'Demo',
//        'sex' => 'male',
//        'phone' => ['15238527275', '13163278019']
//    ];
//    $array = array_flatten($array);
//    return dd($array);


    // array_forget 函数将会用「点」符号从深度嵌套数组移除给定的键值对
//    $array = ['names' => ['joe' => ['programmer']]];
//    array_forget($array, 'names.joe');
//    return dd($array);

    // array_get 函数将会使用「点」符号从深度嵌套数组取回给定的值
//    $array = ['names' => ['joe' => ['programmer']]];
//    $value[] = array_get($array, 'names.joe');
//    $value[] = array_get($array, 'names.john', 'default');
//    return dd($value);

    // array_only 函数将会只从数组返回给定的键值对。
//    $array = ['name' => 'Joe', 'age' => 27, 'votes' => 1];
//    $array = array_only($array, ['name', 'votes']);
//    return dd($array);

    // array_pluck 函数将会从数组拉出给定键值对的清单
//    $array = [['name' => 'Taylor'], ['name' => 'Dayle']];
//    $array = array_pluck($array, 'name');
//    return dd($array);

    // array_set 函数将会使用「点」符号在深度嵌套数组中指定值。
//    $array = ['names' => ['programmer' => 'Joe']];
//    array_set($array, 'names.editor', 'Taylor');
//    array_set($array, 'names.programmer', 'Demo');
//    return dd($array);

    // array_sort 函数通过给定闭包的结果来排序数组。
//    $array = [
//        ['name' => 'Jill'],
//        ['name' => 'Barry']
//    ];
//    $array = array_values(array_sort($array, function($value)
//    {
//        return $value['name'];
//    }));
//    return dd($array);

    // 使用给定的闭包过滤数组。
//    $array = [100, '200', 300, '400', 500];
//    $array = array_where($array, function($key, $value)
//    {
//        return is_int($value);
//    });
//    return dd($array);

    // 返回数组中第一个元素
//    $array = [5, 4, 3, 2, 1];
//    $first = head($array);
//    return dd($first);

    // 返回数组中最后一个元素。对方法链很有用
//    $array = [5, 4, 3, 2, 1];
//    $last = last($array);
//    return dd($last);

    // app_path 取得app文件夹的完整路径
    $path['app_path'] = app_path();
    // base_path 取得应用程序安装根目录的完整路径
    $path['base_path'] = base_path();
    // 获取 config 目录的完整路径
    $path['config_path'] = config_path();
    // 取得 public 文件夹的完整路径
    $path['public_path'] = public_path();
    // 取得 app/storage 文件夹的完整路径
    $path['storage_path'] = storage_path();
//    return dd($path);

    // 把给定的字串转换成 驼峰式命名
//    $camel = camel_case('foo_bar_baz');
//    return dd($camel);

    // 取得给定类的类名称，不含任何命名空间的名称
//    $class = class_basename('Foo\Bar\Baz');
//    return dd($class);

    // 对给定字串执行 htmlentities，并支持 UTF-8
//    $entities = e('<html>foo</html>');
//    return dd($entities);

    // 判断句子结尾是否有给定的字串
//    $value = ends_with('This is my name', 'name');
//    return dd($value);

    // 判断句子是否开头有给定的字串
//    $value = starts_with('This is my name', 'This');
//    return dd($value);

    // 判断句子是否有给定的字串
//    $value = str_contains('This is my name', 'is');
//    return dd($value);

    // 把给定的字串转换成 蛇形命名
//    $snake = snake_case('fooBarBaz');
//    return dd($snake);

    // 限制字串的字符数量
//    $str = str_limit('This is my name.', $limit = 6, $end = '...');
//    return dd($str);

    // 加一个给定字串到句子结尾。多余一个的给定字串则移除
//    $str = str_finish('this/string', '/');
//    $str = str_finish('this/string', '/', 'test');
//    return dd($str);

    // 判断字串是否符合给定的模式。星号可以用来当作通配符
//    $value = str_is('foo*', 'foobar');
//    return dd($value);

    // 把字串转换成它的多数形态 (只有英文)
//    $plural = str_plural('city');
//    return dd($plural);

    // 产生给定长度的随机字串
//    $str = str_random(600);
//    return dd($str);

    // 把字串转换成它的单数形态 (只有英文)
//    $singular = str_singular('cities');
//    return dd($singular);

    // 从给定字串产生一个对网址友善的「slug」
//    $title = str_slug($title = "Laravel 5 Framework", $separator = '-');
//    return dd($title);

    // 把给定字串转换成 首字大写命名
//    $str = studly_case('foo bar baz');
//    $str = studly_case('foo_bar_baz');
//    return dd($str);

    // 翻译给定的语句。等同 Lang::get
//    $value = trans('validation.required');
//    return dd($value);

    // 随着词形变化翻译给定的语句。等同 Lang::choice。
//    $value = trans_choice('foo.bar', 0);
//    return dd($value);

    // 产生给定控制器行为的网址
//    $url = action('HomeController@index', ['user' => 'demo']);
//    return dd($url);

    // 产生给定路由名称的网址。
//    $url = route('routeName', ['user' => 'demo']);
//    return dd($url);

    // 产生资源的网址。
//    $url = asset('img/photo.jpg');
//    return dd($url);

    // 产生给定资源的 HTTPS HTML 链接
//    $url = secure_asset('foo/bar.zip', $title = 'test', $attributes = ['user' => 'demo']);
//    return dd($url);

    // 产生给定路径的 HTTPS 完整网址
//    $url = secure_url('foo/bar', $parameters = ['name' => 'demo', 'age' => 22]);
//    return dd($url);

    // 产生给定路径的完整网址
//    $url = url('foo/bar', $parameters = ['user' => 'demo', 'age' => 22], $secure = null);
//    return dd($url);

    // 返回 取得现在 CSRF token 的值
//    $token = csrf_token();
//    return dd($token);

    // 打印给定变量并结束脚本执行
//    dd('End Script');

    // 获取带版本号的 Elixir 文件的路径
//    elixir($file)

    // 获取一个环境变量的值，如果没有则返回一个默认值。
//    $env = env('APP_ENV', $default = 'production');
//    return dd($env);

    // 触发一个事件
//    event('my.event');

    // 如果给定的值是个 闭包，返回 闭包 的返回值。不是的话，则返回值
//    $value = value(function() { return 'foo'; });
//    $value = value('foo_bar');
//    return dd($value);

    // 用给定的视图路径取得一个视图实例
//    return view('errors.404');

    // 返回给定对象
//    $value = with(new Foo)->doWork();

});


/**
// HTTP路由
// 基本GET路由
Route::get('foo/get', function(){
    return '基本GET路由';
});
// 其他基础路由
Route::post('foo/post', function () {
    return '基本POST路由';
});
Route::put('foo/put', function () {
    return 'PUT路由';
});
Route::delete('foo/delete', function () {
    return 'DELETE路由';
});
// 多种请求注册路由
Route::match(['get', 'post'], 'foo/match', function(){
    return '匹配多种请求路由';
});
// 注册路由响应所有HTTP请求
Route::any('foo/any', function(){
    // url()辅助函数可用于生成对应的url
    // 如：此处生成的url为http://demohub.demo/foo/any
    $url = url('foo/any');
    return $url . '  ' . '响应所有路由';
});
// 路由参数
// 基础路由参数
Route::get('foo/user/{id}', function($id){
    return '基础路由参数：' . 'User ' . $id;
});
// 基础路由多参数
Route::get('foo/user/{id}/page/{num}', function($id, $num){
    return '基础路由多参数：' . 'User ' . $id . ' Page ' . $num;
});
// 可选择的路由参数
Route::get('foo/username/{name?}', function($name = null){
    return '可选择的路由参数：' . $name;
});
// 带默认值的路由参数
Route::get('foo/userdef/{name?}', function($name = 'Demo'){
    return '带默认值的路由参数：' . $name;
});
//使用正则表达式限制参数
Route::get('foo/userlimit/{name}', function($name){
    return '使用正则限制参数：' . $name;
})
    ->where('name', '[A-Za-z]+');
Route::get('foo/userlimit/{id}/{name}', function($id, $name){
    return '使用数组限制多参数：' . 'id ' . $id . ' name ' . $name;
})
    ->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
//也可定义全局模式
//如果想让特定路由参数总是遵循特定的正则表达式
//可以使用pattern方法
//在RouteServiceProvider的boot方法里定义模式
// $route->pattern('id', '[0-9]+');
//
// 取得路由参数
// userget($id, $name), 即可在控制器方法中使用路由参数
Route::get('foo/userget/{id}/{name}', 'Test\TestsController@userget');
Route::get('foo/usergetR/{id}/{name}', 'Test\TestsController@usergetR');

// 命名路由
Route::get('foo/rename/route', ['as' => 'foo_rr', function(){
    return '命名路由';
}]);
// 为控制器动作指定路由名称
Route::get('foo/rename/route/controller', [
    'as' => 'foo_rrc', 'uses' => 'Test\TestsController@redirect'
]);

// 路由分组
// prefix指定url前缀， namespace指定控制器的命名空间， middleware指定中间件
Route::group(['prefix' => 'foo/group', 'namespace' => 'Test'], function()
{
    Route::get('tests/redirect', 'TestsController@redirect');
    Route::resource('tests', 'TestsController');
});
// 注册子域名路由
Route::group(['domain' => '{account}.demohub.demo'], function(){
    Route::get('foo/user/{id}', function($account, $id){
        return 'account: ' . $account . ' id: ' . $id;
    });
});
// 带参数的路由前缀, 并可用正则限制参数
Route::group(['prefix'  => 'foo/account/{account_id}', 'where' => ['account_id' => '[0-9]+'],], function(){
    Route::get('detail', function($account_id){
        return 'account_id: ' . $account_id;
    });
});
 */

Route::get('test/route/{post}', function($post) {
    dd($post);
});
Route::get('test/route-bind/{post}', 'Test\TestsController@getRouteBind');
Route::get('test/route-model/{post}', 'Test\TestsController@getRouteModel');
Route::controllers(['test' => 'Test\TestsController']);

/**
 * IoC 容器学习用例
 */
/**
class FooBaz {}
class FooBar {
    public $baz;
    public function __construct(FooBaz $baz) {
        $this->baz = $baz;
    }
}
// app()->bind()
// 此处如果没有手动绑定, 也无异常抛出(type-hint 为类名)
// Laravel 的IoC容器已经帮助我们实现了
//App::bind('FooBar', function() {
//    return new FooBar(new FooBaz);
//});
// ReflectionException in RouteDependencyResolverTrait.php line 57: Class FooBar does not exist
// ReflectionException in Container.php line 791: Class FooBaz does not exist
Route::get('ioc/foobar', function(FooBar $bar) {
    dd($bar, $bar->baz);
});
*/

/**
interface FooBarInterface {}
class FooBar implements FooBarInterface {}
//class SecondFooBar implements FooBarInterface {}
// 如果此处没有手动绑定, 会抛出异常(type-hint 为接口名)
//App::bind('FooBarInterface', function() {
//    return new FooBar();
//});
// 如果需要FooBarInterface的实例, 就传递FooBar类给它
App::bind('FooBarInterface', 'FooBar');
//App::bind('FooBarInterface', 'SecondFooBar');
// BindingResolutionException in Container.php line 745: Target [FooBarInterface] is not instantiable.
Route::get('ioc/bar', function() {
    $bar = App::make('FooBarInterface');
            // app()->make('FooBarInterface')
            // app()['FooBarInterface']
            // app('FooBarInterface']
//    dd($bar);
});
Route::get('ioc/foobar', function(FooBarInterface $bar) {
    dd($bar);
});
 */

Route::controller('ioc/foo', 'FooController');

Route::get('ioc/bar', function() {
    // 在 App\Providers\Foo\FooServiceProvider 中绑定了FooBuilder 到容器, 这里就可以直接使用
//    return app('FooBuilder')->rights();

//    return app('foo')->rights();
    // 至此可以使用Laravel的 Facade
    return dd(Foo::rights());
});

// 事件监听学习测试用例
// Event::listen 是事件的侦听器和执行器
// 也可以传递参数给事件监听器
Event::listen('user.access', function($clientIp) {
//    dd('This is Event Listening.');
    Log::notice('An access comes from ' . $clientIp);
});

Route::get('event/listen', function() {
    // Event::fire是事件的触发器
//    Event::fire('user.access');
    $clientIp = Request::getClientIp();
    Event::fire('user.access', $clientIp);
});

Route::get('event/front', function() {
//    Event::fire(new App\Events\UserFrontEvent());
    $clientIp = Request::getClientIp();
    Event::fire('access.front', $clientIp);
});

// 缓存学习用例
// 所有保存在缓存中的对象皆会被序列化，所以您可以任意保存各种类型的数据
Route::get('cache/put', function() {
    // 保存对象到缓存中
    Cache::put('key', 'value', $minutes = 1);
    Cache::put('title', 'This is title', \Carbon\Carbon::now()->addMinutes(1));
    Cache::put('content', 'This is content.', \Carbon\Carbon::now()->addMinutes(1));
    // 支持数组缓存
    Cache::put('array', ['title' => 'This is title', 'content' => 'This is content.'], \Carbon\Carbon::now()->addMinutes(1));
    // 支持对象缓存
    Cache::put('obj', new \Carbon\Carbon(), \Carbon\Carbon::now()->addMinutes(1));
    // 缓存不存在时, 执行添加, 返回true
    // 缓存已存在时, 不再添加, 返回false
    Cache::add('not-exist', 'value', 1);

    // 从缓存中取得对象，而当此对象不存在时会保存一个默认值, 返回该对象的值
    // 第三个参数必须为闭包函数
    $value = Cache::remember('remember', $minutes = 1, function() {
        return 'remember value';
    });
    var_dump($value);
    // ErrorException in Repository.php line 196:
    // Argument 3 passed to Illuminate\Cache\Repository::remember() must be an instance of Closure, string given
    // $value = Cache::remember('rememberString', 1, 'string not Closure.');
    // var_dump($value);
    // remember 和 forever 结合使用
    $value = Cache::rememberForever('rememberForever', function() {
        return 'remember & forever.';
    });
    var_dump($value);



    /*
    // 使用 Carbon 对象配置缓存过期时间
    $expiresAt = Carbon::now()->addMinutes(10);
    Cache::put('key', 'value', $expiresAt);

    // 若是对象不存在，则将其存入缓存中
    // 当对象确实被加入缓存时，使用 add 方法将会返回 true 否则会返回 false 。
    Cache::add('key', 'value', $minutes);

    // 确认对象是否存在
    if (Cache::has('key'))
    {
        //
    }

    // 从缓存中取得对象
    $value = Cache::get('key');

    // 取得对象或是返回默认值
    $value = Cache::get('key', 'default');
    $value = Cache::get('key', function() { return 'default'; });

    // 永久保存对象到缓存中
    Cache::forever('key', 'value');
    */
});

Route::get('cache/get/{key}', function($key) {
    // 当缓存时间过期时, 执行get会删除该缓存文件(文件夹保留)
    $value = Cache::get($key);
    var_dump($value);
    // 当使用多种缓存存储时，你可以通过 store 方法来访问它们
     $value = Cache::store('file')->get($key);
    dd($value);
});

Route::get('cache/has/{key}', function($key) {
    // 缓存存在, 且未过期, 返回true
    dd(Cache::has($key));
});

Route::get('cache/pull/{key}', function($key) {
    // 从缓存中取得对象后将它删除
    $value = Cache::pull($key);
    dd($value);
});

Route::get('cache/forget/{key}', function($key) {
    // 从缓存中删除对象
    $value = Cache::forget($key);
    dd($value);
});

// 除了数据库以外的缓存系统都支持递增和递减操作
Route::get('cache/increment/{amount?}', function($amount = null) {
    $amount === null ? Cache::increment('increment') : Cache::increment('increment', $amount);
});
Route::get('cache/decrement/{amount?}', function($amount = null) {
    $amount === null ? Cache::decrement('decrement') : Cache::decrement('decrement', $amount);
});

/**
缓存标签
    注意： 文件或数据库这类缓存系统均不支持缓存标签。此外，使用带有「forever」的缓存标签时，挑选 memcached 这类缓存系统将获得最好的性能，它会自动清除过期的纪录。
访问缓存标签
缓存标签允许您标记缓存内的相关对象，然后使用特定名称更新所有缓存标签。要访问缓存标签可以使用 tags 方法。
您可以保存缓存标签，通过将有序标签列表当作参数传入，或者作为标签名称的有序数组：
Cache::tags('people', 'authors')->put('John', $john, $minutes);
Cache::tags(['people', 'artists'])->put('Anne', $anne, $minutes);

您可以结合使用各种缓存保存方法与标签，包含 remember, forever, 和 rememberForever 。您也可以从已标记的缓存中访问对象，以及使用其他缓存方法如 increment 和 decrement 。
从已标记的缓存中访问对象

要访问已标记的缓存，可传入相同的有序标签列表。
$anne = Cache::tags('people', 'artists')->get('Anne');
$john = Cache::tags(['people', 'authors'])->get('John');

您可以更新所有已标记的对象，使用指定名称或名称列表。例如，以下例子将会移除带有 people 或 authors 或者两者皆有的所有缓存标签，所以「Anne」和「John」皆会从缓存中被移除:
Cache::tags('people', 'authors')->flush();

对照来看，以下例子将只会移除带有 authors 的标签，所以「John」会被移除，但是「Anne」不会。
Cache::tags('authors')->flush();
 */

// Cache类默认支持的监听事件有以下4种
/**
Event::listen('cache.hit', function($key, $value) {
//
});

Event::listen('cache.missed', function($key) {
//
});

Event::listen('cache.write', function($key, $value, $minutes) {
//
});

Event::listen('cache.delete', function($key) {
//
});
 */

Route::get('request/url', function() {
    dd(Request::url(), Request::path(), Request::segment(1), Request::server(), Request::server('REQUEST_URI'), Request::secure(), Request::format());
    dd(app('request')->server);
    dd(Request::getRequestUri());
});

// sweet-alert 测试
Route::get('sweet/alert/{type?}', function($type = null) {
    switch ($type) {
        case null:
        case 'info':
            alert('Title', 'Message'); break;
        case 'success':
            alert()->success('Title', 'Message'); break;
        case 'error':
            alert()->error('Title', 'Message'); break;
        case 'overlay':
            alert()->overlay('Title', 'Message', 'error'); break;
        default:
            alert('Title', 'Message'); break;
    }
    return view('sweetalert');
});

// Laravel中的集合 学习
Route::get('collection', function() {
    // 新建一个集合
    $sites = collect([
        'http://google.com',
        'http://plus.google.com',
        'http://facebook.com',
        'http://twitter.com',
        'http://search.twitter.com',
        'http://apple.com'
    ]);
    dump($sites);

    // 遍历集合中的元素[items], 将回调函数作用于每一个元素
    $sitesAfterMap = $sites->map(function($site) {
        return str_replace('http://', 'http://www.', $site);
    });
    dump($sitesAfterMap);

    // 遍历集合中的所有元素[items], 用回调函数处理每一个元素, 回调返回true, 则删除该元素
    $sitesAfterReject = $sites->reject(function($site) {
        return str_contains($site, 'facebook') == true;
    });
    dump($sitesAfterReject);

    // 返回集合的数组形式
    $sitesArr = $sites->all();
    dump($sitesArr);

    // 求集合元素的平均值
    $avg = collect(['1', '2', '3', '4'])->avg();
    $avgWithStr = $sites->avg();
    $avgWithKey = collect([
        ['name' => 'Aaa', 'age' => 20],
        ['name' => 'Bbb', 'age' => 30],
        ['name' => 'Ccc', 'age' => 24],
        ['name' => 'Ddd', 'age' => 26],
    ])->avg('age');
    dump($avg, $avgWithStr, $avgWithKey);

    // 将一个集合分割成多个 类似array_chunk()
    $chunk = $sites->chunk(2);
    dump($chunk);

    // 类似array_merge() 合并为一维, 相同的键名仅保留一个值
    $collection = collect([
        ['color'=>'blue',4,2],
        ['x','y','color'=>'red','shape'=>'circle',300],
        ['make'=>'Acura','type'=>'NSX']
    ]);
    $collectionAfterCollapse = $collection->collapse();
    dump($collection, $collectionAfterCollapse);

    // 判断指定元素是否在集合中
    $collection=collect([
        'color'=>'blue',
        4,
        2,
        'x',
        'y',
        'shape'=>'circle',
        300,
        'make'=>'Acura',
        'type'=>'NSX'
    ]);
    $nestedCollection=collect([
        [
            'color'=>'blue',
            4,
            2,
            'x',
            'y',
            'shape'=>'circle',
            300,
            'make'=>'Acura',
            'type'=>'NSX'
        ]
    ]);
    // 当传递参数只有一个且为字符串而不是闭包时, 检查的 值, 而不是 键。参考 in_array($key, $this->items)
//    dump($collection->contains('blue'));    // true
//    dump($collection->contains('color'));   // false
    // 当传递参数第二个参数为空时, 返回的总为true
    // 原因为 date_get($target = 'value', $key = 'nothing') 总是返回 null
    // 而 null == '' 为true
    dump($collection->contains('nothing', ''));
    // 如果想用这种方式检查指定的键值对是否存在, 只能用于嵌套类型的collection
    dump($collection->contains('type', 'NSX'));
//    dump($nestedCollection->contains('type', 'NSX'));
    // 针对非嵌套类型的collection, 也可以传递一个闭包, 来检查指定的键值对是否存在
//    dump($collection->contains(function($key, $value) {
//        return ($key == 'type' && $value == 'NSX');
//    }));
    // 用 or 连接时, 总是返回 true , 原因不详
    // 原因已查到, 只有当集合中的数组全部是名称键值对的时候(关联数组), 才能正确返回true or false
    // 之所以会出现这种情况的原因是,     function($key, $value) {return ($key == 'foo' || $value == 'test');}
    // 变量集合中的items属性元素, 作为参数传递进闭包时, 如果是索引数组, 如 0 == 'foo', 这种比较会把字符串转换为数字 为 0,
    // 所以返回的是true, 针对索引数组, 可以使用 === 全等于来比较
//    dump($collection->contains(function($key, $value) {
//        return ($key == 'testKey' || $value == 'testValue');
//    }));    //true
//    dump(collect(['123', '456'])->contains(function($key, $value) {
//        return ($key == 'test' || $value == 'test');
//    }));    //true
//    dump(collect(['foo' => '123', '456'])->contains(function($key, $value) {
//        return ($key == 'test' || $value == 'test');
//    }));    //true
//    dump(collect(['foo' => '123', 'bar' => '456'])->contains(function($key, $value) {
//        return ($key == 'test' || $value == 'test');
//    }));    //false
//    dump(collect(['foo' => '123', 'bar' => '456'])->contains(function($key, $value) {
//        return ($key == 'foo' || $value == 'test');
//    }));    //true
    echo '=============================';
//    dump(collect(['123', '456', 'test'])->contains(function($key, $value) {
//        return ($key === 'foo' || $value === 'bar');
//    }));
    // 检查是否包含对应的键
    dump($collection->contains(function($key) {
        return $key === 'make';
    }));

    // 统计集合中的元素个数
    dump($collection->count($collection));

    // 类似array_diff() 对比差异
    $want=collect(['Apple','Google','Twitter','Cisco','Dell','HP']);
    $notHiring=collect(['Apple','Google']);
    dump($want->diff($notHiring));

    $collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    // 遍历集合中的元素, 满足条件return false时终止循环
    $collection->each(function($value) {
        if ($value > 5) return false;
        echo $value;
    });

    // 遍历集合中的元素, 根据参数从offset 开始取, 间隔 step 个元素, 组合成新的集合
    dump($collection->every(2, 1));

    // 参考 array_filter(), 仅保留满足条件的元素
    dump($collection->filter(function($value) {
        if ($value % 2 == 0) return true;
    }));

    // 返回满足条件的第一个元素
    dump($collection->first());
    dump($collection->first(function($key, $value) {
//        if ($value > 2) return true;
        return $value > 2;
    }));

    // 将多维数组递归变为一维 参考array_walk_recursive()
    $nestedCollection = collect([
        'foo' => 'this is foo.',
        'bar' => ['this is bar.', 'this is bar, too.'],
        'baz' => ['this is baz.', 'fac' => ['this is fac.', 'this is fac, too.']]
    ]);
    dump($nestedCollection->flatten());

    // 键和值互换  参考 array_flip()
//    dump($nestedCollection->flip());    // array_flip(): Can only flip STRING and INTEGER values!
    dump(collect(['foo' => 'Hello', 'bar' => 'World', 'baz' => '!'])->flip());

    $collection = collect(['foo' => 'Hello', 'bar' => 'World', 'baz' => '!']);
    // 删除集合中指定的元素
    dump($collection->forget('foo'));

    $collection = collect([
        ['url'=>'google.com'],
        ['url'=>'facebook.com'],
        ['url'=>'amazon.com'],
        ['url'=>'youtube.com'],
        ['url'=>'yahoo.com'],
        ['url'=>'wikipedia.org'],
        ['url'=>'ebay.com'],
        ['url'=>'twitter.com'],
        ['url'=>'craigslist.com'],
        ['url'=>'reddit.com'],
        ['url'=>'netflix.com'],
        ['url'=>'linkedin.com'],
        ['url'=>'bing.com'],
        ['url'=>'pinterest.com'],
        ['url'=>'apple.com'],
        ['url'=>'instagram.com'],
        ['url'=>'msn.com'],
        ['url'=>'walmart.com'],
        ['url'=>'yelp.com'],
        ['url'=>'weather.com'],
        ['url'=>'zillow.com'],
        ['url'=>'wordpress.com'],
        ['url'=>'target.com'],
        ['url'=>'buzzfeed.com'],
        ['url'=>'microsoft.com'],
    ]);
    // 对集合中的元素取切片 参考array_slice(), 类似分页
    dump($collection->forPage($page = 3, $perPage = 2));

    $collection = collect(['foo' => 'Hello', 'bar' => 'World', 'baz' => '!']);
    // 获取集合中对应的元素 参考 array_key_exists()
    dump($collection->get('foo'));

    $collection = collect([
        ['search'=>'google.com'],
        ['social'=>'facebook.com'],
        ['shopping'=>'amazon.com'],
        ['entertainment'=>'youtube.com'],
        ['entertainment'=>'yahoo.com'],
        ['info'=>'wikipedia.org'],
        ['shopping'=>'ebay.com'],
        ['social'=>'twitter.com'],
        ['info'=>'craigslist.com'],
        ['entertainment'=>'reddit.com'],
        ['entertainment'=>'netflix.com'],
        ['career'=>'linkedin.com'],
        ['search'=>'bing.com'],
        ['entertainment'=>'pinterest.com'],
        ['shopping'=>'apple.com'],
        ['social'=>'instagram.com'],
        ['info'=>'msn.com'],
        ['shopping'=>'walmart.com'],
        ['info'=>'yelp.com'],
        ['info'=>'weather.com'],
        ['shopping'=>'zillow.com'],
        ['blogging'=>'wordpress.com'],
        ['shopping'=>'target.com'],
        ['entertainment'=>'buzzfeed.com'],
        ['software'=>'microsoft.com'],
    ]);
    // 见名知意, 分组, 支持字符串和闭包
    dump($collection->groupBy('search'));

    $collection = collect(['foo' => 'Hello', 'bar' => 'World', 'baz' => '!']);
    // 判断指定的键是否存在于集合元素中 参考 array_key_exists()
    dump($collection->has('foo'));

    $collection = collect([
        ['weather'=>'sunshine','activity'=>'swimming'],
        ['weather'=>'cloudy','activity'=>'working'],
        ['weather'=>'snow','activity'=>'skiing'],
        ['weather'=>'rain','activity'=>'coding'],
    ]);
    // 参考 implode()  数组连接为字符串
    dump($collection->implode('weather', ' => '));

    $collection1 = collect([1,2,3,4,5,6]);
    $collection2 = collect([5,6,7,8,9,10]);
    // 求交集 参考 array_intersect()
    dump($collection1->intersect($collection2));

    // 判断是否为空
    dump(collect([])->isEmpty());
    dump(collect(['foo'])->isEmpty());

    dd('123');
});

Route::get('/apply/upload', function() {
    return view('upload');
});

Route::post('/apply/upload', function() {
    // getting all of the post data
    $file = array('image' => Input::file('image'));
    // setting up rules
    $rules = array('image' => 'required',);     //mimes:jpeg,bmp,png and for max size max:10000
    // doing the validation, passing post data, rules and the messages
    $validator = Validator::make($file, $rules);
    if ($validator->fails()) {
        // send back to the page with the input data and errors
        return Redirect::to('/apply/upload')->withInput()->withErrors($validator);
    } else {
        // checking file is valid.
        if (Input::file('image')->isValid()) {
            $destinationPath = storage_path('uploads');   // upload path
            $extension = Input::file('image')->getClientOriginalExtension();    // getting image extension
            $fileName = rand(11111,99999).'.'.$extension;   // renaming image
            Input::file('image')->move($destinationPath, $fileName);    // uploading file to given path
            // sending back with message
            Session::flash('success', 'Upload successfully');
            return Redirect::to('/apply/upload');
        } else {
            // sending back with error message.
            Session::flash('error', 'uploaded file is not valid');
            return Redirect::to('/apply/upload');
        }
    }
});
